﻿// ExcelTool.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

#include <iostream>
#include "libxl\libxl.h"
#include <string>
#include "windows.h"
#include <direct.h>
#include <vector>
#include <time.h>
#include <fstream>

#include <cstdlib>
#include <math.h>
#include "tlhelp32.h"
#include "stdio.h"

#include <iomanip>
#include <sstream>

#include<iterator>
#include<cctype>
#include<unordered_map>

using namespace libxl;
using namespace std;


string strModelPath = "D:\\project\\c++\\ExcelTool\\Debug\\model.xls";  //xlsx   model.xls   model.xlsx  example.xlsx
string strGenParamPath = "D:\\project\\c++\\ExcelTool\\Debug\\Param.xls";  //xlsx   model.xls   model.xlsx  example.xlsx
wchar_t  strFail[]  = L"失败";
wchar_t  strPass[]  = L"通过";

wchar_t  LibXLName[] = L"111";
wchar_t  LibXLKey[]  = L"windows-2629280d05c1ea0169bd686aa1p2m1lc";

enum eDataItemType {
    e_0OK = 0,
    e_1NA = 1,
    e_2NoStdData = 2,
    e_3NoMeasData = 3,
    e_4NoStdData_NoMeasData = 4,
    e_5Header = 5,
};


#define  _DataLen  7
enum eDataIndex {
    e_0HeaderIndex = 0,
    e_1NameIndex = 1,
    e_2TpyeIndex = 2,
    e_3StdDataIndex = 3,
    e_4MeasDataIndex = 4,
    e_5RangeIndex    = 5,
    e_6DiffDataIndex = 6,
    e_7PassIndex = 7,
    e_8OutRangeDataIndex = 8
};


std::string to_string_with_width(int value, std::size_t width) {
    std::ostringstream stream;
    // 设置宽度并使用0填充未使用的宽度
    stream << std::setw(width) << std::setfill('0') << value;
    return stream.str();
}

std::string doubleToString(double value, int precision) {
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(precision) << value;
    return oss.str();
}
//Converting a WChar string to a Ansi string
std::string WChar2Ansi(LPCWSTR pwszSrc)
{
    int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);
    if (nLen <= 0)
        return std::string("");
    char* pszDst = new char[nLen];
    if (NULL == pszDst)
        return std::string("");
    WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);
    pszDst[nLen - 1] = 0;
    std::string strTemp(pszDst);
    delete[] pszDst;
    return strTemp;
}
string ws2s(wstring& inputws)
{
    return WChar2Ansi(inputws.c_str());
}
//Converting a Ansi string to WChar string
std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen)
{
    int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
    if (nSize <= 0) 
        return  wstring(L"");;
    WCHAR* pwszDst = new WCHAR[nSize + 1];
    if (NULL == pwszDst)
        return NULL;
    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, pwszDst, nSize);
    pwszDst[nSize] = 0;
    if (pwszDst[0] == 0xFEFF) // skip Oxfeff
        for (int i = 0; i < nSize; i++)
            pwszDst[i] = pwszDst[i + 1];
    wstring wcharString(pwszDst);
    delete pwszDst;
    return wcharString;
}
static wstring Str2Wstr(string str)
{
    return Ansi2WChar(str.c_str(), str.size());
}


/// </calss CReportData>
class  CReportData
{
public:
    CReportData();
    ~CReportData();

public:
    int   m_nRow;
    eDataItemType  m_eDataType;
    string m_strHeader;
    string m_strName;
    string m_strType;
    string m_strDevRange;

    string m_strStdData;
    string m_strMeasData;
    //string m_strDiffData;
    //string m_strPass;
    //string m_strOutRangeData;

    float m_fStdData;
    float m_fMeasData;
    float m_fDevRangeUpData;
    float m_fDevRangeDownData;
    float m_fDiffData;
    bool  m_bIsPass;
    float m_fOutRangeData;


public:
    bool MatchNameAndType(string strInName_1, string strInType_1, string strInName_2, string strInType_2);
    bool UpdateVal();
    bool ParseRange(string strInRange);
    void Clear();

};

CReportData::CReportData()
{
    m_nRow = -1;
    m_strHeader = "";
    m_strName = "";
    m_strType = "";
    m_fStdData = 0;
    m_fMeasData = 0;
    m_fDevRangeUpData = 0;
    m_fDevRangeDownData = 0;
    m_fDiffData = 0;
    m_bIsPass = false;
    m_fOutRangeData = 0;
}

CReportData::~CReportData()
{
}
void CReportData::Clear()
{
    m_nRow = -1;
    m_strHeader = "";
    m_strName = "";
    m_strType = "";
    m_fStdData = 0;
    m_fMeasData = 0;
    m_fDevRangeUpData = 0;
    m_fDevRangeDownData = 0;
    m_fDiffData = 0;
    m_bIsPass = false;
    m_fOutRangeData = 0;
}
bool CReportData::MatchNameAndType(string strInName_1, string strInType_1, string strInName_2, string strInType_2)
{
    if ((0 == strInName_1.size()) or (0 == strInType_1.size()))
    {
        return false;
    }

    if ((strInName_1.size() == strInName_2.size()) and (strInType_1.size() == strInType_2.size()))
    {
        return true;
    }
    else
    {
        return false;
    }
}
bool CReportData::UpdateVal()
{
    m_fDiffData = m_fMeasData - m_fStdData;
    if ((m_fDiffData > m_fDevRangeUpData) or (m_fDiffData < m_fDevRangeDownData))
    {
        m_bIsPass = false;
        if (m_fDiffData > m_fDevRangeUpData)
        {
            m_fOutRangeData = m_fDiffData - m_fDevRangeUpData;
        }
        if (m_fDiffData < m_fDevRangeDownData)
        {
            m_fOutRangeData = m_fDiffData -m_fDevRangeDownData;
        }
    }
    else
    {
        m_fOutRangeData = 0;
        m_bIsPass = true;
    }
    return true;
}
bool CReportData::ParseRange(string strInRange)
{
    //"±1.000"   +0.200/0.000   +2.000/-1.000   N/A    公差  ""
    int nLen = strInRange.size();
    if (nLen == 0)
    {
        m_fDevRangeUpData = 0;
        m_fDevRangeDownData = 0;
        return false;
    }
    string str, str2;
    int nRet = strInRange.find("±");
    if (nRet >= 0)
    {
        str = strInRange.substr(nRet+2);
        m_fDevRangeUpData = abs(stof(str));
        m_fDevRangeDownData = m_fDevRangeUpData * (-1);

    }
    int nRet1 = strInRange.find("+");
    if (nRet1 >= 0)
    {
        int nRet2 = strInRange.find("/");
        str = strInRange.substr(nRet1 + 1, nRet2-1- nRet1);
        str2 = strInRange.substr(nRet2 + 1);
        m_fDevRangeUpData = (stof(str));
        m_fDevRangeDownData = (stof(str2));
    }
    if ( (-2 == (nRet + nRet1)) and !(strInRange.compare("N/A")==0) and !(strInRange.compare("公差")==0))
    {
        m_fDevRangeUpData = abs(stof(strInRange));
        m_fDevRangeDownData = 0 ;
    }

    return true;
}

/// </class CReportData>


/// </calss CXls>
class CXls
{
public:
    CXls()
    {
        m_pBook = NULL;
        m_pSheet = NULL;
    };
    ~CXls()
    {
        if (m_pBook != NULL)
        {
            m_pBook->release();
            m_pSheet = NULL;
        }
    };

private:
    Book* m_pBook;
    Sheet* m_pSheet;
    int m_nRowSIze;

public:
    bool LoadXlFile(string strFilename, bool bIsCreateNew);
    bool SaveXlFile(string strFilename);
    
    int  GetRowSize() { return m_nRowSIze; };

    bool GetLineVal(int nRow, vector<int> vnCol, CReportData &CData);  
    bool SetLineVal(int nRow, CReportData& CData);
    bool SetVal(float vfData, int vnRow,int vnCol);
    bool SetString(string vstrVal, int vnRow, int vnCol, int vnColorType);

};


bool CXls::LoadXlFile(string strFilepath,bool bIsCreateNew)
{
    //m_pBook = xlCreateXMLBook();   //
    m_pBook = xlCreateBook();
    m_nRowSIze = 0;

    m_pBook->setKey(LibXLName, LibXLKey);
    std::wstring addr = Str2Wstr(strFilepath);
    const wchar_t* pFilepath = addr.c_str();
    if (bIsCreateNew)
    {
        m_pSheet = m_pBook->addSheet(L"Sheet1");
    }
    else
    {
        if (!m_pBook->load(pFilepath))
        {
            m_pBook->release();
            m_pBook = NULL;
            return false;
        }
        else
        {
            m_pSheet = m_pBook->getSheet(0);
            m_nRowSIze = m_pSheet->lastRow();
        }
    }
    return true;
}

bool CXls::SaveXlFile(string strFilepath)
{
    if ((m_pBook == NULL) or (m_pSheet == NULL))
    {
        return false;
    }

    std::wstring addr = Str2Wstr(strFilepath);
    const wchar_t* pFilepath = addr.c_str();
    if (m_pBook->save(pFilepath))
    {
        //std::wcout << "\nFile " << *pFilepath << " has been modified." << std::endl;
        //::ShellExecute(NULL, L"open", pFilepath, NULL, NULL, SW_SHOW);
        return true;
    }
    else
    {
        std::cout << m_pBook->errorMessage() << std::endl;
        return false;
    }
}

bool CXls::SetVal(float fData, int nRow, int nCol)
{
    if ((m_pBook != NULL) and (m_pSheet != NULL))
    {
        if ((nRow >= 0) and (nRow < m_pSheet->lastRow()))
        {
            m_pSheet->writeNum(nRow, nCol, fData);
            return true;
        }
        else
        {
            return false;
        }
        }
        else
        {
            return false;
        }
}
bool  CXls::SetString(string strVal, int nRow, int nCol, int nColorType)
{
    if ((m_pBook != NULL) and (m_pSheet != NULL))
    {
        if ((nRow >= 0) and (nRow < m_pSheet->lastRow()))
        {
            Font* Font = m_pBook->addFont();
            Font->setColor(COLOR_WHITE);
            Font->setSize(8);

            Format* FailFormat = m_pBook->addFormat();
            FailFormat->setFillPattern(FILLPATTERN_SOLID);
            FailFormat->setPatternForegroundColor(COLOR_RED);
            FailFormat->setFont(Font);

            Format* PassFormat = m_pBook->addFormat();
            PassFormat->setFillPattern(FILLPATTERN_SOLID);
            PassFormat->setPatternForegroundColor(COLOR_GREEN);
            PassFormat->setFont(Font);

            for (int ind = 0; ind < strVal.size(); ind++)
            {
                if (strVal.size() == 0)
                {
                    continue;
                }
                std::wstring wstr = Str2Wstr(strVal);
                const wchar_t* pwchar = wstr.c_str();
                switch (nColorType)
                {
                case 0:  //无
                    m_pSheet->writeStr(nRow, nCol, pwchar);
                    break;
                case 1:   //green
                    m_pSheet->writeStr(nRow, nCol, strPass, PassFormat);
                    break;
                case 2:  //red
                    m_pSheet->writeStr(nRow, nCol, strFail, FailFormat);
                    break;
                default:
                    break;
                }

            }
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }

}
bool CXls::SetLineVal(int nRow,CReportData& CData)
{
    if ((m_pBook != NULL) and (m_pSheet != NULL))
    {
        if ((nRow >= 0) and (nRow < m_pSheet->lastRow()))
        {
            int nType;
            //4 6 7 8
            switch (CData.m_eDataType)
            {
            case e_0OK:
                SetVal(CData.m_fMeasData, nRow, e_4MeasDataIndex);
                SetVal(CData.m_fDiffData, nRow, e_6DiffDataIndex);
                if (CData.m_fOutRangeData != 0)
                {
                    SetVal(CData.m_fOutRangeData, nRow, e_8OutRangeDataIndex);
                }
                nType = CData.m_bIsPass ? 1 : 2;
                SetString("00", nRow, e_7PassIndex, nType);
                break;
            case e_1NA:
                break;
            case e_2NoStdData:
                SetVal(CData.m_fMeasData, nRow, e_4MeasDataIndex);
                SetVal(CData.m_fDiffData, nRow, e_6DiffDataIndex);
                if (CData.m_fOutRangeData != 0)
                {
                    SetVal(CData.m_fOutRangeData, nRow, e_8OutRangeDataIndex);
                }
                nType = CData.m_bIsPass ? 1 : 2;
                SetString("00", nRow, e_7PassIndex, nType);
                break;
            case e_3NoMeasData:
                break;
            case e_4NoStdData_NoMeasData:
                break;
            case e_5Header:
                SetString(CData.m_strName, nRow, e_1NameIndex, 0);
                break;
            default:
                break;
            }
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}
bool CXls::GetLineVal(int nRow, vector<int> vnCol,CReportData& CData)  
{
    if ((m_pBook != NULL) and (m_pSheet != NULL))
    {
        if((nRow >= 0)and(nRow < m_pSheet->lastRow()))
        {
            float fRange = 0;
            CData.m_nRow = nRow;
            CellType retStdType = CELLTYPE_ERROR;
            CellType retMeasType = CELLTYPE_ERROR;
            for (int ind = 0; ind < vnCol.size(); ind++)
            {
                switch (vnCol[ind])
                {
                case eDataIndex::e_0HeaderIndex:
                    CData.m_strHeader = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    break;
                case eDataIndex::e_1NameIndex:
                    CData.m_strName = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    break;
                case eDataIndex::e_2TpyeIndex:
                    CData.m_strType = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    break;
                case eDataIndex::e_3StdDataIndex:
                    CData.m_fStdData = m_pSheet->readNum(nRow, vnCol[ind]);
                    CData.m_strStdData = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    retStdType = m_pSheet->cellType(nRow, vnCol[ind]);
                    break;
                case eDataIndex::e_4MeasDataIndex:
                    CData.m_fMeasData = m_pSheet->readNum(nRow, vnCol[ind]);
                    CData.m_strMeasData = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    retMeasType = m_pSheet->cellType(nRow, vnCol[ind]);
                    break;
                case eDataIndex::e_5RangeIndex:
                    CData.m_strDevRange = WChar2Ansi(m_pSheet->readStr(nRow, vnCol[ind]));
                    fRange   = m_pSheet->readNum(nRow, vnCol[ind]);
                    break;
                //case DataIndex::e_6DiffDataIndex:
                //    break;
                //case DataIndex::e_7PassIndex:
                //    break;
                //case DataIndex::e_8OutRangeDataIndex:
                //    break;
                default:
                    break;
                }
            }

            int ret1 = CData.m_strStdData.compare("N/A");
            int ret2= CData.m_strMeasData.compare("N/A");
            int ret3 = CData.m_strDevRange.compare("N/A");
            if ((CData.m_strStdData.compare("N/A") == 0) and (CData.m_strMeasData.compare("N/A") == 0) and (CData.m_strDevRange.compare("N/A") == 0))
            {
                CData.m_eDataType = eDataItemType::e_1NA;
                return true;
            }

            //
            if (CData.m_strDevRange.size() > 0)
            {
                CData.ParseRange(CData.m_strDevRange);
                CData.UpdateVal();
                if ((retMeasType == CELLTYPE_EMPTY) or (retMeasType == CELLTYPE_BLANK))
                {
                    CData.m_fMeasData = 0;
                    CData.m_fDiffData = 0;
                    CData.m_fOutRangeData = 0;
                }
                if ((retStdType == CELLTYPE_EMPTY) or (retStdType == CELLTYPE_BLANK))
                {
                    CData.m_fStdData = 0;
                }
            }
            else
            {
                if (!(fRange == 0))
                {
                    CData.m_fDevRangeUpData = fRange;
                } 
            }
            //
            if (CData.m_strHeader.size() > 0)
            {
                CData.m_eDataType = eDataItemType::e_5Header;
            }
            else
            {
                CData.m_eDataType = eDataItemType::e_0OK;
                if( (retStdType == CELLTYPE_EMPTY)or(retStdType == CELLTYPE_BLANK) )
                {
                    CData.m_eDataType = eDataItemType::e_2NoStdData;
                }
                if( (retMeasType == CELLTYPE_EMPTY) or (retMeasType == CELLTYPE_BLANK) )
                {
                    CData.m_eDataType = eDataItemType::e_3NoMeasData;
                }
                if( ((retStdType == CELLTYPE_EMPTY) or (retStdType == CELLTYPE_BLANK)) and ((retMeasType == CELLTYPE_EMPTY) or (retMeasType == CELLTYPE_BLANK)))
                {
                    CData.m_eDataType = eDataItemType::e_4NoStdData_NoMeasData;
                }
            }

            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}
/// /////////////
/// </calss CXls>
/// 


//tool function 

std::string type_str[20];
bool GetCorrentPath(string& strPath)
{
    char* buffer;
    //可以将buffer作为输出参数
    if ((buffer = _getcwd(NULL, 0)) == NULL)
    {
        return false;
    }
    else
    {
        strPath = string(buffer);
        free(buffer);
        return true;
    }
}
string GenPathFromTime()
{
    time_t current_time = time(NULL);
    struct tm  timeinfo;
    localtime_s(&timeinfo, &current_time);
    int nYear = timeinfo.tm_year + 1900;
    int nMonth = timeinfo.tm_mon + 1;
    string strSavePath =  to_string_with_width(nYear, 2) + to_string_with_width(nMonth, 2) + to_string_with_width(timeinfo.tm_mday, 2) + "_" + \
        to_string_with_width(timeinfo.tm_hour, 2) + to_string_with_width(timeinfo.tm_min, 2) + to_string_with_width(timeinfo.tm_sec, 2) + ".xls";
    return strSavePath;
}

float Gendata(float infData,float infParam)
{
    float fParam = infParam == 0 ? 0.03 : infParam;  //default param
    srand(time(0));
    int randVal = rand() % 100;
    float outfData = infData + float(((randVal - 50.0) > 0, 1, -1)) * randVal / 100.0 * fParam;
    return outfData;
}


bool write_txtfile(std::string filepath, vector<std::string>* pvInString)
{
    std::ofstream outfile(filepath);
    if (!outfile.is_open())
    {
        return false;
    }
    else
    {
        for (int i = 0; i < pvInString->size(); i++)
        {
            outfile << pvInString->at(i);
            outfile << "\n";
        }
        outfile.close();
        return true;
    }
}

/// 
/// 
#define _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3       0    

int main()
{
    string strExePath;
    GetCorrentPath(strExePath); //model.xls
    strModelPath = strExePath + "\\model.xls";
    string strRawDataPath = strExePath + "\\rawdata.xls";
    strGenParamPath = strExePath + "\\Sparam.xls";
    string strCalibrateParamPath = strExePath + "\\Bparam.xls";

    //读取数据
    vector<CReportData> vModelReportDatas;
    CXls* pModelExcel = new CXls();
    vector<int> vnColIndexs{ 0, 1,2,3,4,5 };
    pModelExcel->LoadXlFile(strModelPath, false);
    int nModelRowSize = pModelExcel->GetRowSize();
    CReportData DataItem;
    for (int ind = 0; ind < nModelRowSize; ind++)
    {
        //if (ind == 388)  {  cout << "index" << ind<<endl;  }
        DataItem.Clear();
        if (pModelExcel->GetLineVal(ind, vnColIndexs, DataItem))
        {
            vModelReportDatas.push_back(DataItem);
        }
    }

    //测量初值
    vector<CReportData> vRawdataReportDatas;
    CXls* pRawdataExcel = new CXls();
    pRawdataExcel->LoadXlFile(strRawDataPath, false);
    int nRawdataRowSize = pRawdataExcel->GetRowSize();
    for (int ind = 0; ind < nRawdataRowSize; ind++)
    {
        DataItem.Clear();
        if (pRawdataExcel->GetLineVal(ind, vnColIndexs, DataItem))
        {
            vRawdataReportDatas.push_back(DataItem);
        }
    }

    //读取补偿参数
    vector<CReportData> vCalibrateParamDatas;
    vector<int> vnParamColIndexs{ 1,2,3 };
    CXls* pCalibrateParamExcel = new CXls();
    pCalibrateParamExcel->LoadXlFile(strCalibrateParamPath, false);
    int nCalibrateParamRowSize = pCalibrateParamExcel->GetRowSize();
    for (int ind = 0; ind < nCalibrateParamRowSize; ind++)
    {
        DataItem.Clear();
        if (pCalibrateParamExcel->GetLineVal(ind, vnParamColIndexs, DataItem))
        {
            vCalibrateParamDatas.push_back(DataItem);
        }
    }

    //读取生成参数
    vector<CReportData> vGenParamDatas;
    CXls* pGenParamExcel = new CXls();
    pGenParamExcel->LoadXlFile(strGenParamPath, false);
    int nGenParamRowSize = pGenParamExcel->GetRowSize();
    for (int ind = 0; ind < nGenParamRowSize; ind++)
    {
        DataItem.Clear();
        if (pGenParamExcel->GetLineVal(ind, vnParamColIndexs, DataItem))
        {
            vGenParamDatas.push_back(DataItem);
        }
    }

    vector<CReportData> vReportXYDatas;
    //更新数据
    vector<int> vAllInfo_Index;
    vector<int> vAllData_All;
    vector<int> vAllData_Meas;
    vector<int> vAllData_Pass;
    int AllData_All = 0, AllData_Meas = 0, AllData_Pass = 0;

    vector<CReportData> *pvReportDatas = &vRawdataReportDatas;
    vector<CReportData> *pvParamDatas = &vCalibrateParamDatas;
    CXls* pCXl = pRawdataExcel;
    int nDataRowSize, nParamRowSize;
    bool bIsAddZ_OK  = (0 == _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3) and (nRawdataRowSize == nCalibrateParamRowSize);
    if (bIsAddZ_OK)
    {
        pCXl = pRawdataExcel;
        pvReportDatas = &vRawdataReportDatas;
        nDataRowSize = nRawdataRowSize;
        pvParamDatas = &vCalibrateParamDatas;
        nParamRowSize = nCalibrateParamRowSize;
    }
    bool bIsGenXY_OK = (1 == _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3) and (nModelRowSize   == nGenParamRowSize);
    if (bIsGenXY_OK)
    {
        pCXl = pModelExcel;
        pvReportDatas = &vModelReportDatas;
        nDataRowSize = nModelRowSize;
        pvParamDatas = &vGenParamDatas;
        nParamRowSize = nGenParamRowSize;
    }

    bool bIsGenZ_OK  = (2 == _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3) and (nRawdataRowSize == nGenParamRowSize);
    if (bIsGenZ_OK)
    {
        pCXl = pRawdataExcel;
        pvReportDatas = &vRawdataReportDatas;
        nDataRowSize = nRawdataRowSize;
        pvParamDatas = &vGenParamDatas;
        nParamRowSize = nGenParamRowSize;
    }

    if(bIsAddZ_OK or bIsGenXY_OK or bIsGenZ_OK)
    {
        for (int ind = 0; ind < nDataRowSize; ind++)
        {
            //if (ind == 388)    {   //cout << "index" << ind << endl;  }
            if ((pvReportDatas->at(ind).m_eDataType == e_0OK) or (pvReportDatas->at(ind).m_eDataType==e_2NoStdData))
            {
                bool bIsHXY = (pvReportDatas->at(ind).m_strType.compare("X") == 0) or  (pvReportDatas->at(ind).m_strType.compare("Y") == 0);
                bool bIsHZ  = (pvReportDatas->at(ind).m_strType.compare("Z") == 0) and (pvReportDatas->at(ind).m_strName.find("H")    >  -1);
                bool bIsHXYZ = bIsHXY or bIsHZ;
                switch (_M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3)
                {
                case 0:
                    if (!bIsHXYZ)
                    {
                        pvReportDatas->at(ind).m_fMeasData = pvReportDatas->at(ind).m_fMeasData + vCalibrateParamDatas[ind].m_fStdData;
                    }
                    break;
                case 1:
                    if (bIsHXYZ)
                    {
                        pvReportDatas->at(ind).m_fMeasData = Gendata(pvReportDatas->at(ind).m_fMeasData, vGenParamDatas[ind].m_fStdData);
                        vReportXYDatas.push_back(pvReportDatas->at(ind));
                    }
                    break;
                case 2:
                    if (!bIsHXYZ)
                    {
                        pvReportDatas->at(ind).m_fMeasData = Gendata(pvReportDatas->at(ind).m_fMeasData, vGenParamDatas[ind].m_fStdData);
                    }
                    break;
                default:
                    break;
                }
                //
                pvReportDatas->at(ind).UpdateVal();
            } 
            pCXl->SetLineVal(ind, pvReportDatas->at(ind));


            //统计计数
            if (pvReportDatas->at(ind).m_strType.size() > 0)
            {
                AllData_All++;
                if(  (pvReportDatas->at(ind).m_eDataType != e_3NoMeasData) and \
                     (pvReportDatas->at(ind).m_eDataType != e_1NA)         and \
                     (pvReportDatas->at(ind).m_eDataType != e_4NoStdData_NoMeasData)  )  //非NA 有测量值
                {
                    AllData_Meas++;
                    if (pvReportDatas->at(ind).m_bIsPass)
                    {
                        AllData_Pass++;
                    }
                }
            }
            int ret = pvReportDatas->at(ind).m_strHeader.compare("全部统计");
            if (ret ==0 )
            {
                vAllInfo_Index.push_back(ind);
                vAllData_All.push_back(AllData_All);
                vAllData_Meas.push_back(AllData_Meas);
                vAllData_Pass.push_back(AllData_Pass);

            }
        }
        //统计计数
        vAllData_All.push_back(AllData_All);
        vAllData_Meas.push_back(AllData_Meas);
        vAllData_Pass.push_back(AllData_Pass);


        //********更新统计数据
        for(int ind2=0;ind2< vAllInfo_Index.size();ind2++)
        {
            vAllData_All[ind2]  = vAllData_All[ind2+1] - vAllData_All[ind2] - 1;
            vAllData_Meas[ind2] = vAllData_Meas[ind2 + 1] - vAllData_Meas[ind2] - 1;
            vAllData_Pass[ind2] = vAllData_Pass[ind2 + 1] - vAllData_Pass[ind2] - 1;
            //总共: 10, 测量的 : 8 (80.000 %), 通过 : 7 (70.000 %), 失败 : 1 (10.000 %), 警告 : 0 (0.000 %)
            float fMeas =100 * float(vAllData_Meas[ind2]) / (float)vAllData_All[ind2];
            float fPass = 100 * float(vAllData_Pass[ind2]) / (float)vAllData_Meas[ind2];
            pvReportDatas->at(vAllInfo_Index[ind2]).m_strName = string("总共:") + to_string(vAllData_All[ind2]) + \
                ", 测量的 : " + to_string(vAllData_Meas[ind2]) + \
                " (" + doubleToString(fMeas, 3) + "%), 通过 :" + to_string(vAllData_Pass[ind2]) + \
                "7 (" + doubleToString(fPass, 3) + " %), 失败 : " + to_string(vAllData_Meas[ind2] - vAllData_Pass[ind2]) + \
                " (" + doubleToString(100.0 - fPass,3) + "%), 警告 : 0 (0.000 %)";
            pCXl->SetLineVal(vAllInfo_Index[ind2], pvReportDatas->at(vAllInfo_Index[ind2]));
        }
    }
 
    bool bIsTransXY_OK = (3 == _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3) and (nCalibrateParamRowSize > 0);
    if (bIsTransXY_OK)
    {
        for (int ind = 0; ind < vCalibrateParamDatas.size(); ind++)
        {
            bool bIsHXY = (vCalibrateParamDatas[ind].m_strType.compare("X") == 0) or (vCalibrateParamDatas[ind].m_strType.compare("Y") == 0);
            bool bIsHZ = (vCalibrateParamDatas[ind].m_strType.compare("Z") == 0) and (vCalibrateParamDatas[ind].m_strName.find("H")    > -1);
            if (bIsHXY or bIsHZ)
            {
                vReportXYDatas.push_back(vCalibrateParamDatas[ind]);
            }
        }
    }


    //输出文件
    if( _M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3 == 1)
    {
        unordered_map<string, vector<CReportData>> strMap;
        for(int ind=0;ind< vReportXYDatas.size();ind++)
        {
            unordered_map<string, vector<CReportData>>::iterator it = strMap.find(vReportXYDatas[ind].m_strName);
            if (it == strMap.end())
            {
                vector<CReportData> vItem;
                vItem.push_back(vReportXYDatas[ind]);
                strMap.insert(unordered_map<string, vector<CReportData>>::value_type(vReportXYDatas[ind].m_strName, vItem));
            }
            else 
            {
                strMap[vReportXYDatas[ind].m_strName].push_back(vReportXYDatas[ind]);
            }      
        }
        vector<string> vstrXYInfos;
        unordered_map<string, vector<CReportData>>::iterator iItem;
        for (iItem = strMap.begin(); iItem != strMap.end(); iItem++)
        {
            if (iItem->second.size() > 0)
            {
                string strItem = iItem->first;
                string strX = "0", strY = "0", strZ = "0";

                bool bFoundX = false, bFoundY = false, bFoundZ = false;
                for (int ind = 0; ind < iItem->second.size(); ind++)
                {
                    if (!bFoundX and (iItem->second.at(ind).m_strType.compare("X") == 0))
                    {
                        strX = doubleToString(iItem->second.at(ind).m_fMeasData, 3);
                        bFoundX = true;
                    }
                    if (!bFoundY and (iItem->second.at(ind).m_strType.compare("Y") == 0))
                    {
                        strY = doubleToString(iItem->second.at(ind).m_fMeasData, 3);
                        bFoundY = true;
                    }
                    if (!bFoundZ and (iItem->second.at(ind).m_strType.compare("Z") == 0))
                    {
                        strZ = doubleToString(iItem->second.at(ind).m_fMeasData, 3);
                        bFoundZ = true;
                    }
                }
                strItem = strItem + "," + strX + "," + strY + "," + strZ;
                vstrXYInfos.push_back(strItem);
            }
        }
        if(vstrXYInfos.size() > 0)
        {
            write_txtfile(strExePath + "\\xyval.txt", &vstrXYInfos);
        }
    }
    else
    {
        string strSavePath = strExePath + "\\" + GenPathFromTime();
        pCXl->SaveXlFile(strSavePath);
        if (_M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3 == 0)
        {
            pCXl->SaveXlFile(strExePath + "\\model.xls");
        }
    }


    //输出补偿参数txt
    if (_M_GenMode_AddZ0_GenXY1_GenZ2_TransXY3 == 3)
    {
        unordered_map<string, vector<CReportData>> strMap;
        for (int ind = 0; ind < vReportXYDatas.size(); ind++)
        {
            unordered_map<string, vector<CReportData>>::iterator it = strMap.find(vReportXYDatas[ind].m_strName);
            if (it == strMap.end())
            {
                vector<CReportData> vItem;
                vItem.push_back(vReportXYDatas[ind]);
                strMap.insert(unordered_map<string, vector<CReportData>>::value_type(vReportXYDatas[ind].m_strName, vItem));
            }
            else
            {
                strMap[vReportXYDatas[ind].m_strName].push_back(vReportXYDatas[ind]);
            }
        }
        vector<string> vstrXYInfos;
        unordered_map<string, vector<CReportData>>::iterator iItem;
        for (iItem = strMap.begin(); iItem != strMap.end(); iItem++)
        {
            if (iItem->second.size() > 0)
            {
                string strItem = iItem->first;
                string strX = "0", strY = "0", strZ = "0";

                bool bFoundX = false, bFoundY = false, bFoundZ = false;
                for (int ind = 0; ind < iItem->second.size(); ind++)
                {
                    if (!bFoundX and (iItem->second.at(ind).m_strType.compare("X") == 0))
                    {
                        strX = doubleToString(iItem->second.at(ind).m_fStdData, 3);
                        bFoundX = true;
                    }
                    if (!bFoundY and (iItem->second.at(ind).m_strType.compare("Y") == 0))
                    {
                        strY = doubleToString(iItem->second.at(ind).m_fStdData, 3);
                        bFoundY = true;
                    }
                    if (!bFoundZ and (iItem->second.at(ind).m_strType.compare("Z") == 0))
                    {
                        strZ = doubleToString(iItem->second.at(ind).m_fStdData, 3);
                        bFoundZ = true;
                    }
                }
                strItem = strItem + "," + strX + "," + strY + "," + strZ;
                vstrXYInfos.push_back(strItem);
            }
        }
        if(vstrXYInfos.size() > 0)
        {
            write_txtfile(strExePath + "\\Bparam.txt", &vstrXYInfos);
        }
    }

    return 0;

}
